TypeScript 55.4%
Python 43.2%
SQL 1.2%
1import Link from "next/link";2import type { Metadata } from "next";3import { Timeline } from "@/components/timeline";4import { Chip, Empty, PageHeader, Panel, Table, Td } from "@/components/ui";5import { api } from "@/lib/api";6import { relTime } from "@/lib/format";78export const dynamic = "force-dynamic";910export async function generateMetadata({ params }: { params: Promise<{ domain: string }> }): Promise<Metadata> {11 const { domain } = await params;12 return { title: `${domain} — domain timeline`, description: `Monitored URLs and detected changes on ${domain}.`, alternates: { canonical: `/domain/${domain}` } };13}1415export default async function DomainPage({ params, searchParams }: { params: Promise<{ domain: string }>; searchParams: Promise<{ cursor?: string }> }) {16 const { domain } = await params;17 const { cursor } = await searchParams;18 const d = await api.domain(domain, cursor);19 return (20 <>21 <PageHeader kicker="Domain" title={<span className="font-mono">{domain}</span>} description="Every monitored URL on this domain with its history, plus the event timeline." actions={d?.source_id ? <Link href={`/source/${d.source_id}`} className="rounded-md border border-line bg-panel px-2.5 py-1 text-[12px] hover:border-line-strong">Source page →</Link> : undefined} />22 <div className="grid gap-4 lg:grid-cols-[1fr_1fr]">23 <Panel title={`URLs · ${d?.urls.length ?? 0}`} dense>24 {d?.urls.length ? (25 <Table head={["URL", "Status", "Snapshots", "Changes", "Last seen"]}>26 {d.urls.map((u) => (27 <tr key={u.url}>28 <Td><Link href={`/url?u=${encodeURIComponent(u.url)}`} className="block max-w-[26rem] truncate font-mono text-[11.5px] hover:underline">{u.url.replace(/^https?:\/\//, "")}</Link></Td>29 <Td><Chip tone={u.status === "active" ? "ok" : u.status === "removed" ? "danger" : "warn"}>{u.status}</Chip></Td>30 <Td mono>{u.snapshot_count}</Td>31 <Td mono>{u.change_count}</Td>32 <Td mono className="text-fg-subtle">{relTime(u.last_seen_at)}</Td>33 </tr>34 ))}35 </Table>36 ) : (37 <Empty>No URLs monitored on this domain yet.</Empty>38 )}39 </Panel>40 <Panel title="Timeline" dense>41 <Timeline events={d?.events ?? []} />42 {d?.nextCursor && (43 <div className="flex justify-end px-3 py-2 text-[12px]">44 <Link href={`/domain/${domain}?cursor=${encodeURIComponent(d.nextCursor)}`} className="rounded-md border border-line bg-panel-2 px-2.5 py-1 hover:border-line-strong">Older →</Link>45 </div>46 )}47 </Panel>48 </div>49 </>50 );51}52